home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue29 / system / Midetree / mwIDETree.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-09-16  |  13.5 KB  |  482 lines

  1. unit mwIDETree;
  2. {
  3.   Vcl IDETree Expert
  4.  
  5.   Author:  Martin_Waldenburg
  6.   Created: 09.97
  7.   Version: 0.3 beta
  8.   Status: FreWare
  9.   The RTTI routines are slightly modified
  10.   from the book " Secrets of Delphi 2 "  by Ray Lischner.
  11.   In my opinion the best Delphi book.
  12.   Used with permision. Thanks Ray. 
  13.   Secret30.dpl needed.
  14. }
  15.  
  16. interface
  17.  
  18. uses SysUtils,
  19.   Classes,
  20.   Messages,
  21.   Consts,
  22.   Forms,
  23.   Windows,
  24.   Dialogs,
  25.   ClipBrd,
  26.   Controls,
  27.   EditIntf,
  28.   ExptIntf,
  29.   ToolIntf,
  30.   ExtCtrls,
  31.   Menus,
  32.   comCtrls,
  33.   StdCtrls,
  34.   LibIntf,
  35.   TypInfo,
  36.   WinTypes,
  37.   S_Rtti;
  38.  
  39. type
  40.   TfrmIDETree = class(TForm)
  41.     Memo1: TMemo;
  42.     TreeView1: TTreeView;
  43.     Splitter1: TSplitter;
  44.     procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
  45.     procedure FormShow(Sender: TObject);
  46.     procedure TreeView1Deletion(Sender: TObject; Node: TTreeNode);
  47.   private
  48.     { private declarations }
  49.   public
  50.     { public declarations }
  51.   end;
  52.  
  53.   TIDETreeExpert = class(TIExpert)
  54.   private
  55.     MenuItem: TIMenuItemIntf;
  56.   protected
  57.     procedure OnClick( Sender: TIMenuItemIntf); virtual;
  58.   public
  59.     constructor Create; virtual;
  60.     destructor Destroy; override;
  61.     function GetName: string; override;
  62.     function GetAuthor: string; override;
  63.     function GetStyle: TExpertStyle; override;
  64.     function GetIDString: string; override;
  65.   end;
  66.  
  67. procedure Register;
  68. procedure WriteTypeInfo(Info: PTypeInfo);
  69.  
  70. var
  71.   frmIDETree: TfrmIDETree;
  72.   TopNode, Level1Child, Level2Child, Level3Child, Level4Child: TTreenode;
  73.  
  74. implementation
  75.  
  76. {$R *.DFM}
  77.  
  78. procedure Register;
  79. begin
  80.   RegisterLibraryExpert(TIDETreeExpert.Create);
  81. end;
  82.  
  83. { TIDETreeExpert code }
  84. function TIDETreeExpert.GetName: String;
  85. begin
  86.   Result := 'IDETreeExpert'
  87. end;
  88.  
  89. function TIDETreeExpert.GetAuthor: String;
  90. begin
  91.   Result := 'Martin_Waldenburg'; { author }
  92. end;
  93.  
  94. function TIDETreeExpert.GetStyle: TExpertStyle;
  95. begin
  96.   Result := esAddIn;
  97. end;
  98.  
  99. function TIDETreeExpert.GetIDString: String;
  100. begin
  101.   Result := 'private.IDETreeExpert';
  102. end;
  103.  
  104. constructor TIDETreeExpert.Create;
  105. var
  106.   Main: TIMainMenuIntf;
  107.   ReferenceMenuItem: TIMenuItemIntf;
  108.   Menu: TIMenuItemIntf;
  109. begin
  110.   inherited Create;
  111.   MenuItem := nil;
  112.   if ToolServices <> nil then begin { I'm an expert! }
  113.     Main := ToolServices.GetMainMenu;
  114.     if Main <> nil then begin { we've got the main menu! }
  115.       try 
  116.         { add the menu of your choice }
  117.         ReferenceMenuItem := Main.FindMenuItem('ToolsOptionsItem');
  118.         if ReferenceMenuItem <> nil then
  119.         try
  120.           Menu := ReferenceMenuItem.GetParent;
  121.           if Menu <> nil then
  122.           try
  123.             MenuItem := Menu.InsertItem(ReferenceMenuItem.GetIndex+1,
  124.                               'IDETree',
  125.                               'IDETreeExpertItem','',
  126.                               0,0,0,
  127.                               [mfEnabled, mfVisible], OnClick);
  128.           finally
  129.             Menu.DestroyMenuItem;
  130.           end;
  131.         finally
  132.           ReferenceMenuItem.DestroyMenuItem;
  133.         end;
  134.       finally
  135.         Main.Free;
  136.       end;
  137.     end;
  138.   end;
  139. end;
  140.  
  141. destructor TIDETreeExpert.Destroy;
  142. begin
  143.   if MenuItem <> nil then
  144.     MenuItem.DestroyMenuItem;
  145.   inherited Destroy;
  146. end;{Destroy}
  147.  
  148. procedure TIDETreeExpert.OnClick( Sender: TIMenuItemIntf);
  149. begin
  150.   if not Assigned(frmIDETree) then
  151.     frmIDETree := TfrmIDETree.Create(Application);
  152.   frmIDETree.Show;
  153.   frmIDETree.SetFocus
  154. end;
  155.  
  156.  
  157. function AddType(aNode: TTreeNode; Name: String; Info: PTypeInfo): TTreeNode;
  158. begin
  159.   Result:= frmIDETree.TreeView1.Items.AddChild(aNode, Name + ': ' + Info^.Name);
  160.   Result.Data:= TObject(Info); 
  161. end;
  162.  
  163. Function LookupStuff : Boolean;
  164. Var
  165.   i, j, k, l: Integer;
  166. Begin
  167.   frmIDETree.TreeView1.items.clear;
  168.   TopNode:= AddType(nil, Application.Name, Application.ClassInfo);
  169.   frmIDETree.Memo1.Clear;
  170.   Try
  171.   for i:=0 to Application.ComponentCount-1 do
  172.     Begin
  173.       Level1Child:= AddType(TopNode, Application.Components[i].Name,
  174.                     Application.Components[i].ClassInfo);
  175.       for j:=0 to Application.Components[i].ComponentCount-1 do
  176.         begin
  177.           Level2Child:= AddType(Level1Child, Application.Components[i].Components[j].Name,
  178.                         Application.Components[i].Components[j].ClassInfo);
  179.           for k:=0 to Application.Components[i].Components[j].ComponentCount-1 do
  180.             begin
  181.               Level3Child:= AddType(Level2Child, Application.Components[i].Components[j].Components[k].Name,
  182.                             Application.Components[i].Components[j].Components[k].ClassInfo);
  183.               for l:=0 to Application.Components[i].Components[j].Components[k].ComponentCount-1 do
  184.                 begin
  185.                   Level4Child:= AddType(Level3Child, Application.Components[i].Components[j].Components[k].Components[l].Name,
  186.                                 Application.Components[i].Components[j].Components[k].Components[l].ClassInfo);
  187.                 end;
  188.             end;
  189.         end;
  190.       End;
  191.   finally
  192.   End;
  193. End;
  194.  
  195. {$I S_Delphi.inc}
  196.  
  197. { Write the ordinal type. }
  198. procedure WriteOrdType(OrdType: TOrdType);
  199. begin
  200.   frmIDETree.Memo1.Lines.Add('  OrdType: '+ EnumName(Ord(OrdType), TypeInfo(TOrdType)));
  201. end;
  202.  
  203. { Return a string representation of a character. If the character
  204.   is printable ASCII, then return the character in quotes; otherwise
  205.   return the character as an ordinal value, e.g., #0. }
  206. function CharToString(C: Cardinal): string;
  207. begin
  208.   { If C is printable, then print it; otherwise,
  209.     print its ordinal value. }
  210.   if (Chr(C) < ' ') or (C > 127) then
  211.     Result := Format('#%d', [C])
  212.   else
  213.     Result := '''' + Chr(C) + ''''
  214. end;
  215.  
  216. { Write the type information for a character or wide character. }
  217. procedure WriteCharData(Data: PTypeData);
  218. begin
  219.   with Data^ do
  220.   begin
  221.     WriteOrdType(OrdType);
  222.     frmIDETree.Memo1.Lines.Add('  MinValue: ' + CharToString(MinValue));
  223.     frmIDETree.Memo1.Lines.Add('  MaxValue: '+ CharToString(MaxValue));
  224.   end;
  225. end;
  226.  
  227. { Write the information for a single property. }
  228. procedure WritePropInfo(Info: PPropInfo);
  229. begin
  230.   with Info^ do
  231.   begin
  232.     frmIDETree.Memo1.Lines.Add(' property '+ Name+ ': '+ PropType^.Name);
  233.     frmIDETree.Memo1.Lines.Add('   GetProc: '+ Format('%p', [GetProc]));
  234.     frmIDETree.Memo1.Lines.Add('   SetProc: '+ Format('%p', [SetProc]));
  235.     frmIDETree.Memo1.Lines.Add('   StoredProc: '+ Format('%p', [StoredProc]));
  236.     frmIDETree.Memo1.Lines.Add('   Index: '+ IntToStr(Index));
  237.     frmIDETree.Memo1.Lines.Add('   Default: '+ IntToStr(Default));
  238.     frmIDETree.Memo1.Lines.Add('   NameIndex: ' + IntToStr(NameIndex));
  239.   end;
  240. end;
  241.  
  242. { Write the information for all the properties of a class. }
  243. procedure WritePropertyInfo(Info: PTypeInfo; Data: PTypeData);
  244. var
  245.   I: Integer;
  246.   PropList: PPropList;
  247. begin
  248.   GetMem(PropList, Data^.PropCount * SizeOf(PPropInfo));
  249.   try
  250.     GetPropInfos(Info, PropList);
  251.     for I := 0 to Data^.PropCount-1 do
  252.       WritePropInfo(PropList^[I]);
  253.   finally
  254.     FreeMem(PropList, Data^.PropCount * SizeOf(PPropInfo));
  255.   end;
  256. end;
  257.  
  258. { Write the type information for a class. Write all the
  259.   published properties. }
  260. procedure WriteClassData(Info: PTypeInfo; Data: PTypeData);
  261. begin
  262.   with Data^ do
  263.   begin
  264.     frmIDETree.Memo1.Lines.Add('  ClassType: '+ ClassType.ClassName);
  265.     frmIDETree.Memo1.Lines.Add('  ParentInfo: ');
  266.     if ParentInfo = nil then
  267.       frmIDETree.Memo1.Lines.Add('nil')        { TObject has a nil ParentInfo }
  268.     else
  269.       frmIDETree.Memo1.Lines.Add(ParentInfo^.Name);
  270.     frmIDETree.Memo1.Lines.Add('  PropCount: '+ IntToStr(PropCount));
  271.     WritePropertyInfo(Info, Data);
  272.   end;
  273. end;
  274.  
  275. { Write the type information for a floating point type. }
  276. procedure WriteFloatData(Data: PTypeData);
  277. begin
  278.   with Data^ do
  279.     frmIDETree.Memo1.Lines.Add('  FloatType: '+ EnumName(Ord(FloatType), TypeInfo(TFloatType)));
  280. end;
  281.  
  282. { Write the type information for an integer type. }
  283. procedure WriteIntegerData(Data: PTypeData);
  284. begin
  285.   with Data^ do
  286.   begin
  287.     WriteOrdType(OrdType);
  288.     frmIDETree.Memo1.Lines.Add('  MinValue: ' +IntToStr(MinValue));
  289.     frmIDETree.Memo1.Lines.Add('  MaxValue: '+ IntToStr(MaxValue));
  290.   end;
  291. end;
  292.  
  293. { Parameter information is stored in a packed character array.
  294.   The GetParamInfo procedure unpacks the data into a TParamList
  295.   array. }
  296. type
  297.   TParamFlag = (pfVar, pfConst, pfArray);
  298.   TParamFlags = set of TParamFlag;
  299.   PParamString = PShortString;
  300.   TParamInfo = record
  301.     Flags: TParamFlags;
  302.     ParamName: PParamString;
  303.     ParamType: PParamString;
  304.   end;
  305.   TParamList = array[0..255] of TParamInfo;
  306.   PParamList = ^TParamList;
  307.  
  308. { Get the infromation for a parameter list, and store
  309.   it in the ParamList argument. }
  310. procedure GetParamInfo(Data: PTypeData; var Params: TParamList;
  311.                        var ReturnType: PParamString);
  312. var
  313.   I: Integer;
  314.   Ptr: PByte;
  315. begin
  316.   with Data^ do
  317.   begin
  318.     Ptr := PByte(@ParamList);
  319.     for I := 0 to ParamCount-1 do
  320.       with Params[I] do
  321.       begin
  322.         Flags := TParamFlags(Ptr^);
  323.         Inc(Ptr);
  324.         ParamName := PParamString(Ptr);
  325.         Inc(Ptr, Length(ParamName^) + 1);
  326.         ParamType := PParamString(Ptr);
  327.         Inc(Ptr, Length(ParamType^) + 1);
  328.       end;
  329.     if MethodKind = mkFunction then
  330.       ReturnType := PParamString(Ptr);
  331.   end;
  332. end;
  333.  
  334. { Write the information for a method, including all the parameters.
  335.   If the method is a function, then show the return type, too. }
  336.  
  337. procedure WriteMethodData(Data: PTypeData);
  338. var
  339.   I: Integer;
  340.   Params: PParamList;
  341.   Return: PParamString;
  342. begin
  343.   with Data^ do
  344.   begin
  345.     frmIDETree.Memo1.Lines.Add('  MethodKind: '+
  346.        EnumName(Ord(MethodKind), TypeInfo(TMethodKind)));
  347.     frmIDETree.Memo1.Lines.Add('  ParamCount: '+ IntToStr(ParamCount));
  348.  
  349.     { Allocate memory to hold all the parameter information }
  350.     GetMem(Params, ParamCount * SizeOf(TParamInfo));
  351.     try
  352.       GetParamInfo(Data, Params^, Return);
  353.       { Write each parameter: }
  354.       for I := 0 to ParamCount-1 do
  355.         with Params^[I] do
  356.         begin
  357.           frmIDETree.Memo1.Lines.Add('    Param #'+ intToStr(I) + '=');
  358.           if pfVar in Flags then
  359.             frmIDETree.Memo1.Lines.Add('var ');
  360.           if pfConst in Flags then
  361.             frmIDETree.Memo1.Lines.Add('const ');
  362.           Write(ParamName^, ': ');
  363.           if pfArray in Flags then
  364.             frmIDETree.Memo1.Lines.Add('array of ');
  365.           frmIDETree.Memo1.Lines.Add(ParamType^ + ';');
  366.         end;
  367.     finally
  368.       FreeMem(Params, ParamCount * SizeOf(TParamInfo));
  369.     end;
  370.     if MethodKind = mkFunction then
  371.       frmIDETree.Memo1.Lines.Add('  ReturnType: ' + Return^);
  372.   end;
  373. end;
  374.  
  375. { Write the type information for a short string type. }
  376. procedure WriteStringData(Data: PTypeData);
  377. begin
  378.   with Data^ do
  379.     frmIDETree.Memo1.Lines.Add('  MaxLength: ' + IntToStr(MaxLength));
  380. end;
  381.  
  382. { Write the type information for an enumerated type.
  383.   Show all the literal names. If this is a subrange,
  384.   then show the type info of the base type. }
  385. procedure WriteEnumData(Info: PTypeInfo; Data: PTypeData);
  386. var
  387.   I: LongInt;
  388. begin
  389.   with Data^ do
  390.   begin
  391.     WriteOrdType(OrdType);
  392.     frmIDETree.Memo1.Lines.Add('  MinValue: '+ IntToStr(MinValue));
  393.     frmIDETree.Memo1.Lines.Add('  MaxValue: '+ IntToStr(MaxValue));
  394.     frmIDETree.Memo1.Lines.Add('  BaseType:');
  395.     { Avoid an infinite loop when the BaseType is the current type. }
  396.     if BaseType{$ifdef Delphi3}^{$endif} <> Info then
  397.       WriteTypeInfo(BaseType{$ifdef Delphi3}^{$endif});
  398.     frmIDETree.Memo1.Lines.Add('  NameList: (');
  399.     { Show all the enumerated literals }
  400.     for I := MinValue to MaxValue do
  401.     begin
  402.       frmIDETree.Memo1.Lines.Add(EnumName(I, Info));
  403.       if I < MaxValue then
  404.         frmIDETree.Memo1.Lines.Add(', ');
  405.     end;
  406.     frmIDETree.Memo1.Lines.Add(')');
  407.   end;
  408. end;
  409.  
  410. { Write the type information for a set type.
  411.   Also show the base enumerated type. }
  412. procedure WriteSetData(Data: PTypeData);
  413. begin
  414.   with Data^ do
  415.   begin
  416.     WriteOrdType(OrdType);
  417.     WriteTypeInfo(CompType{$ifdef Delphi3}^{$endif});
  418.   end;
  419. end;
  420.  
  421.  
  422. { Write the full type information. }
  423. procedure WriteTypeInfo(Info: PTypeInfo);
  424. var
  425.   Data: PTypeData;
  426. begin
  427.   frmIDETree.Memo1.Lines.Add('TypeInfo(' + Info^.Name + ')=');
  428.   frmIDETree.Memo1.Lines.Add('  Kind: ' + EnumName(Ord(Info^.Kind), TypeInfo(TTypeKind)));
  429.   Data := GetTypeData(Info);
  430.   case Info^.Kind of
  431. {$ifdef WIN32}
  432.   tkWChar,
  433. {$endif}
  434.   tkChar:      WriteCharData(Data);
  435.   tkClass:     WriteClassData(Info, Data);
  436.   tkEnumeration: WriteEnumData(Info, Data);
  437.   tkFloat:     WriteFloatData(Data);
  438.   tkInteger:   WriteIntegerData(Data);
  439.   tkMethod:    WriteMethodData(Data);
  440.   tkSet:       WriteSetData(Data);
  441.   tkString:    WriteStringData(Data);
  442.   { The following have no additional type data. }
  443. {$ifdef Delphi2}
  444.   tkLString, tkVariant,
  445. {$ifdef Delphi3}
  446.   tkWString,
  447. {$endif}
  448. {$endif}
  449.     tkUnknown: ;
  450.   end;
  451. end;
  452.  
  453.  
  454. { TfrmIDETree code }
  455.  
  456. procedure TfrmIDETree.TreeView1Change(Sender: TObject; Node: TTreeNode);
  457. begin
  458.   Memo1.Clear;
  459.   Memo1.Lines.BeginUpdate;
  460.   try
  461.     with TreeView1 do
  462.       WriteTypeInfo(PTypeInfo(Node.Data));
  463.   finally
  464.     Memo1.Lines.EndUpdate;
  465.   end;
  466. end;
  467.  
  468. procedure TfrmIDETree.FormShow(Sender: TObject);
  469. begin
  470.   Memo1.Clear;
  471.   TreeView1.Items.BeginUpdate;
  472.   LookupStuff;
  473.   TreeView1.Items.EndUpdate;
  474. end;
  475.  
  476. procedure TfrmIDETree.TreeView1Deletion(Sender: TObject; Node: TTreeNode);
  477. begin
  478.   Node.Data:= nil;
  479. end;
  480.  
  481. end.
  482.